File: Script.c

package info (click to toggle)
openclonk 8.1-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 169,484 kB
  • sloc: cpp: 180,478; ansic: 108,988; xml: 31,371; python: 1,223; php: 767; makefile: 139; sh: 101
file content (172 lines) | stat: -rw-r--r-- 3,804 bytes parent folder | download | duplicates (5)
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*
	Arrow
	The arrow is the standard ammo for the bow and base object for all other
	types of arrows. This object is stackable (up to 15) as it is required
	from the bow.
	The arrow employs the HitCheck effect (in System.ocg/HitChecks.c) originally
	from Hazard to search for targets during flight.
	
	@author Newton
*/

#include Library_Stackable
#include Library_Flammable


protected func Construction()
{
	SetR(90);
	return _inherited(...);
}

public func Launch(int angle, int str, object shooter, object weapon)
{
	SetShape(-2, -2, 4, 11);
	SetVertex(0, VTX_Y, 3, 1);
	SetVertex(1, VTX_Y, 4, 1);
	SetVertex(2, VTX_Y, -2, 1);
	SetPosition(GetX(), GetY() - 2);
	var xdir = Sin(angle,str);
	var ydir = Cos(angle,-str);
	SetXDir(xdir);
	SetYDir(ydir);
	SetR(angle);
	Sound("Objects::Arrow::Shoot?");
	// Shooter controls the arrow for correct kill tracing.
	SetController(shooter->GetController());
	
	AddEffect("HitCheck", this, 1,1, nil, nil, shooter);
	AddEffect("InFlight", this, 1,1, this);
	return;
}

private func Stick()
{
	if (GetEffect("InFlight",this))
	{
		RemoveEffect("HitCheck",this);
		RemoveEffect("InFlight",this);
	
		SetXDir(0);
		SetYDir(0);
		SetRDir(0);
	
		var x = Sin(GetR(), 9);
		var y = -Cos(GetR(), 9);
		var mat = GetMaterial(x, y);
		// Stick in any material.
		if (mat != -1)
			SetVertex(2, VTX_Y, -10, 1);
	}
	return;
}

public func HitObject(object obj)
{
	// Determine damage to obj from speed and arrow strength.
	var relx = GetXDir() - obj->GetXDir();
	var rely = GetYDir() - obj->GetYDir();
	var speed = Sqrt(relx * relx + rely * rely);
	var dmg = ArrowStrength() * speed * 1000 / 100;
	
	if (WeaponCanHit(obj))
	{
		if (obj->GetAlive())
			Sound("Hits::ProjectileHitLiving?");
		else
			Sound("Objects::Arrow::HitGround");
		
		obj->~OnProjectileHit(this);
		WeaponDamage(obj, dmg, FX_Call_EngObjHit, true);
		WeaponTumble(obj, this->TumbleStrength());
	}
	
	// Stick does something unwanted to controller.
	if (this) 
		Stick();
	return;
}

public func Hit()
{
	if (GetEffect("InFlight",this))
		Sound("Objects::Arrow::HitGround");
	Stick();
}

// The flight effect rotates the arrow according to its speed.
public func FxInFlightStart(object target, proplist effect, int temp)
{
	if (temp) 
		return 1;
	effect.x = target->GetX();
	effect.y = target->GetY();
	return 1;
}

public func FxInFlightTimer(object target, proplist effect, int time)
{
	var oldx = effect.x;
	var oldy = effect.y;
	var newx = GetX();
	var newy = GetY();
	
	// And additionally, we need one check: If the arrow has no speed
	// anymore but is still in flight, we'll remove the hit check.
	if (oldx == newx && oldy == newy)
	{
		// But we give the arrow 10 frames to speed up again.
		effect.var2++;
		if (effect.var2 >= 10)
			return Hit();
	}
	else
		effect.var2 = 0;

	// Rotate arrow according to speed.
	var anglediff = Normalize(Angle(oldx, oldy, newx, newy) - GetR(), -180);
	SetRDir(anglediff / 2);
	effect.x = newx;
	effect.y = newy;
	return 1;
}

protected func UpdatePicture()
{
	var arrow_count = GetStackCount();
	if (arrow_count >= 9) 
		SetGraphics(nil);
	else 
		SetGraphics(Format("%d", arrow_count));
	_inherited(...);
}

protected func Entrance()
{
	// Reset the sticky-vertex.
	SetVertex(2, VTX_Y, 0, 1);
}

protected func RejectEntrance()
{
	// Can't be collected while flying.
	if (GetEffect("InFlight",this)) 
		return true;
	return _inherited(...);
}

public func IsArrow() { return true; }
public func MaxStackCount() { return 15; }
public func ArrowStrength() { return 10; }
public func TumbleStrength() { return 100; }
public func IsArmoryProduct() { return true; }


/*-- Properties --*/

local Name = "$Name$";
local Description = "$Description$";
local Collectible = 1;
local Components = {Wood = 3};
local BlastIncinerate = 5;
local ContactIncinerate = 1;